#pragma once
#include "Buffer.hpp"
#include <mutex>
#include <condition_variable>
#include <functional>
#include <memory>
#include <thread>
#include <atomic>
namespace mylog
{
    using Functor = std::function<void(Buffer &)>;
    enum class AsyncType
    {
        ASYNC_SAFE,  // 安全的阻塞模式
        ASYNC_UNSAFE // 动态扩容
    };
    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        AsyncLooper(const Functor &cb, AsyncType looper_type = AsyncType::ASYNC_SAFE)
            : _stop(false),
              _thread(std::thread(&AsyncLooper::ThreadEntry, this)),
              _call_back(cb),
              _looter_type(looper_type) {}
        ~AsyncLooper()
        {
            Stop();
        }
        void Stop()
        {
            _stop = true;
            _cond_con.notify_all();
            _thread.join();
        }
        void Push(const char *data, size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (AsyncType::ASYNC_SAFE == _looter_type)
                _cond_pro.wait(lock, [&](){ return _pro_buf.WriteableSize() > len; }); // 阻塞模式
            // 动态扩容
            _pro_buf.Push(data, len);
            _cond_con.notify_one();
        }

    private:
        // 线程入口函数
        void ThreadEntry()
        {
            while (true)
            {
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    if(_stop && _pro_buf.Empty())
                    {
                        break;
                    }
                    _cond_con.wait(lock, [&](){ return _stop || !_pro_buf.Empty(); });
                    _con_buf.Swap(_pro_buf);
                    if (AsyncType::ASYNC_SAFE == _looter_type)
                        _cond_pro.notify_all();
                }
                _call_back(_con_buf);
                _con_buf.Reset();
            }
        }

    private:
        std::atomic<bool> _stop; // 工作区停止标志
        Buffer _pro_buf;         // 生产缓冲区
        Buffer _con_buf;         // 消费缓冲区
        std::mutex _mutex;
        std::condition_variable _cond_pro;
        std::condition_variable _cond_con;
        std::thread _thread; // 异步工作器对应的工作线程
        Functor _call_back;  // 对缓冲区数据进行处理的回调函数
        AsyncType _looter_type;
    };
}